#pragma once
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "LogMessage.hpp"

class Sock
{
private:
    const static int gbacklog = 20;
public:
    Sock()
    {}
    static int Socket()//初始化
    {
        int listensock=socket(AF_INET,SOCK_STREAM,0);
        if(listensock<0)
        {
            logMessage(ERROR,"socketerror:%d,%s",errno,strerror(errno));
            exit(1);
        }
        logMessage(DEBUG,"socketerror:%d,%s",errno,strerror(errno));
        return listensock;
    }
    
    static void Bind(int sock, uint16_t port, std::string ip = "0.0.0.0")//绑定
    {
        struct sockaddr_in local;
        memset(&local,0,sizeof local);
        local.sin_family=AF_INET;
        local.sin_port=htons(port);//主机转网络
        inet_pton(AF_INET, ip.c_str(), &local.sin_addr);
        if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
        {
            logMessage(ERROR,"bind:%d,%s",errno,strerror(errno));
            exit(2);
        }
    }
    static void Listen(int sock)//监听
    {
        if(listen(sock,gbacklog)<0)
        {
            logMessage(ERROR,"listen:%d,%s",errno,strerror(errno));
            exit(3);
        }
            logMessage(DEBUG,"listen:%d,%s",errno,strerror(errno));
        
    }
    static int Accept(int sock, std::string *ip, uint16_t *port)//将sock返回值返回给客户端
    {
        struct sockaddr_in src;
        socklen_t len=sizeof(src);

        int servicesock =accept(sock,(struct sockaddr*)&src,&len);
        if(servicesock<0)
        {
            logMessage(ERROR,"accept:%d,%s",errno,strerror(errno));
            exit(4);
        }
        //返回
        if(port) *port = ntohs(src.sin_port);//端口号
        if(ip) *ip = inet_ntoa(src.sin_addr);//IP地址
        return servicesock;
    }
    static bool Connect(int sock, const std::string &server_ip, const uint16_t &server_port)//连接客户端
    {
        struct sockaddr_in server;
        memset(&server,0,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(server_port);
        server.sin_addr.s_addr = inet_addr(server_ip.c_str());
        if(connect(sock,(struct sockaddr*)&server,sizeof(server)==0)) return true;
        else return false;
    }

};
